// Copyright (c) 2012 MIT License by 6.172 Staff

#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <functional>
#include <boost/core/demangle.hpp>
#include <iostream>

using namespace std;

void print() {
    cout << "\n";
}
template<typename T, typename ...Args>
void print(T&& t, Args&&... args) {
    cout << t << " ";
    print(std::forward<Args>(args)...);
}

template<typename T>
void printSize() {
    print("size of", boost::core::demangle(typeid(T).name()), ":", sizeof(T), "bytes");
}

int main() {
  // Please print the sizes of the following types:
  // int, short, long, char, float, double, unsigned int, long long
  // uint8_t, uint16_t, uint32_t, and uint64_t, uint_fast8_t,
  // uint_fast16_t, uintmax_t, intmax_t, __int128, and student

  // Here's how to show the size of one type. See if you can define a macro
  // to avoid copy pasting this code.

    printSize<int>(); printSize<int*>();
    printSize<short>(); printSize<short*>();
    printSize<long>(); printSize<long*>();
    printSize<char>(); printSize<char*>();
    printSize<float>(); printSize<float*>();
    printSize<double>(); printSize<double*>();
    printSize<unsigned int>(); printSize<unsigned int*>();
    printSize<long long>(); printSize<long long*>();
    printSize<uint8_t>(); printSize<uint8_t*>();
    printSize<uint16_t>(); printSize<uint16_t*>();
    printSize<uint32_t>(); printSize<uint32_t*>();
    printSize<uint64_t>(); printSize<uint64_t*>();
    printSize<uint_fast8_t>(); printSize<uint_fast8_t*>();
    printSize<uint_fast16_t>(); printSize<uint_fast16_t*>();
    printSize<uintmax_t>(); printSize<uintmax_t*>();
    printSize<intmax_t>(); printSize<intmax_t*>();
    printSize<__int128>(); printSize<__int128*>();

  // e.g. PRINT_SIZE("int", int);
  //      PRINT_SIZE("short", short);

  // Alternatively, you can use stringification
  // (https://gcc.gnu.org/onlinedocs/cpp/Stringification.html) so that
  // you can write
  // e.g. PRINT_SIZE(int);
  //      PRINT_SIZE(short);

  // Composite types have sizes too.
  typedef struct {
    int id;
    int year;
  } student;

  student you;
  you.id = 12345;
  you.year = 4;

  printSize<student>(); printSize<student*>();

  // Array declaration. Use your macro to print the size of this.
  int x[5];
  printSize<decltype(x)>(); printSize<decltype(&x)>();

  // You can just use your macro here instead: PRINT_SIZE("student", you);
  //printf("size of %s : %zu bytes \n", "student", sizeof(you));

  return 0;
}
